package com.boarsoft.message.store.jdbc;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.SQLSyntaxErrorException;
import java.sql.Statement;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.boarsoft.common.Util;

public abstract class MsgBaseTM {
	private static final Logger log = LoggerFactory.getLogger(MsgBaseTM.class);

	protected String createTblSql;
	protected String createIdxSql;
	protected String insertSql;
	// protected String countSql;
	/** 用于更新消息的主状态 */
	protected String updateSql;
	/** 用于删除过期的消息 */
	protected String deleteSql;
	/** 用于查询某一条消息 */
	protected String getSql;

	protected String schema;
	protected String table;
	protected String index;

	public MsgBaseTM(String target) {
		this.table = new StringBuilder("tbl_").append(target).toString();
		this.index = new StringBuilder("idx_").append(target).toString();
	}

	public void init() {
		this.prepareCreate();
		this.prepareDelete();
		this.prepareGet();
		this.prepareInsert();
		this.prepareUpdate();
	}

	protected void prepareDelete() {
		this.deleteSql = new StringBuilder("delete from ").append(table) //
				.append(" where iAddTime <= ?").toString();
	}

	protected String prepareDelete(String tableName, short... statuses) {
		StringBuilder sb = new StringBuilder("delete from ").append(tableName) //
				.append(" where iAddTime <= ? and tStatus in ( ");
		for (int i = 0; i < statuses.length; i++) {
			if (i != (statuses.length - 1)) {
				sb.append("?,");
			} else {
				sb.append("?)");
			}
		}
		return sb.toString();
	}

	public boolean exists(Connection conn) throws SQLException {
		StringBuilder sb = new StringBuilder();
		sb.append("select id from ").append(table).append(" limit 1");
		Statement s = conn.createStatement();
		try {
			return s.execute(sb.toString());
		} catch (SQLSyntaxErrorException e) {
			return false;
		} finally {
			JdbcUtil.close(s);
		}
//		try {
//			tbs = conn.getMetaData().getTables(null, "boar-message", table, new String[] { "TABLE" });
//			while (tbs.next()) {
//				log.info("Found table {}", tbs.getString("TABLE_NAME"));
//				if (table.equals(tbs.getString("TABLE_NAME"))) {
//					return true;
//				}
//			}
//		} finally {
//			JdbcUtil.close(tbs);
//		}
	}

	public void drop(Connection conn) throws SQLException {
		drop(conn, this.table);
	}

	public void drop(Connection conn, String table) throws SQLException {
		Statement st = null;
		try {
			st = conn.createStatement();
			String dropTblSql = new StringBuilder("drop table ") //
					.append(table).toString();
			log.info("Drop table IF EXISTS {}", table);
			log.debug("SQL:\n{}", dropTblSql);
			st.execute(dropTblSql);
			// String dropIdxSql = new StringBuilder("drop index on \"")//
			// .append(schema).append("\"(cAddTime)").toString();
			// log.info("Drop schema index {}", schema);
			// log.debug("SQL:\n{}", dropIdxSql);
			// st.execute(dropIdxSql);
		} finally {
			JdbcUtil.close(st);
		}
	}

	public void create(Connection conn) throws SQLException {
		create(conn, this.createTblSql, this.createIdxSql);
	}

	public void create(Connection conn, String createTblSql, String createIdxSql) throws SQLException {
		Statement st = null;
		try {
			conn.setAutoCommit(false);
			try {
				st = conn.createStatement();
				st.execute(createTblSql);
				st.execute(createIdxSql);
				conn.commit();
			} catch (Exception e) {
				conn.rollback();
			}
		} finally {
			JdbcUtil.close(st);
		}
	}

	public int truncate(Connection conn, Date date) throws SQLException {
		String before = Util.date2str(date, Util.STDDTMF);
		log.warn("Deleted messages before {}", before);
		PreparedStatement ps = null;
		try {
			ps = conn.prepareStatement(deleteSql);
			ps.setString(1, before);
			return ps.executeUpdate();
		} finally {
			JdbcUtil.close(ps);
		}
	}

	// ---------------

	protected abstract void prepareCreate();

	protected abstract String prepareCreateTbl(String table);

	protected abstract String prepareCreateIdx(String table);

	protected abstract void prepareGet();

	protected abstract void prepareInsert();

	protected abstract void prepareUpdate();

	// ----------------

	public String getInsertSql() {
		return insertSql;
	}

	public void setInsertSql(String insertSql) {
		this.insertSql = insertSql;
	}

	public String getUpdateSql() {
		return updateSql;
	}

	public void setUpdateSql(String updateSql) {
		this.updateSql = updateSql;
	}

	public String getDeleteSql() {
		return deleteSql;
	}

	public void setDeleteSql(String deleteSql) {
		this.deleteSql = deleteSql;
	}

	public String getGetSql() {
		return getSql;
	}

	public void setGetSql(String getSql) {
		this.getSql = getSql;
	}

	public String getSchema() {
		return schema;
	}

	public void setSchema(String schema) {
		this.schema = schema;
	}

	public String getTable() {
		return table;
	}

	public void setTable(String table) {
		this.table = table;
	}

	public String getIndex() {
		return index;
	}

	public void setIndex(String index) {
		this.index = index;
	}
}
